import Head from 'next/head'; import { readdirSync, readFileSync } from 'fs'; import { join } from 'path'; import { CSSProperties, ReactNode, useState } from 'react'; import ReactMarkdown from 'react-markdown'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import rehypeRaw from 'rehype-raw'; import gfm from 'remark-gfm'; import Chapters, { chapter } from '../../components/chapters'; import Image from '../../components/image'; import Navbar, { MobileNavbar } from '../../components/navbar'; import Seperator from '../../components/seperator'; import Tags from '../../components/tag'; export interface ArticleMeta { title?: string; subtitle?: string; author?: string; tags?: Array; date?: string; chapters?: Array; cover?: string; id?: string; } var headingLevel = (input: string) => input?.match(/^[#]+/)[0]?.length || 0; var sectionID = (input: string) => input .replace(/[()\[\]{}!@#$%^&*<>?,./\;':"\\|=+]/g, '') .replace(/\s/g, '-') .toLowerCase(); function Heading(props: { children?: ReactNode; level?: number; }) { var HeadingTag = 'h' + props.level as keyof JSX.IntrinsicElements; return ; } function Code(props: { className?: string; children?: ReactNode; }) { var language = /language-(\w+)/.exec(props.className || ''); if (!language) return ; return ; } export function RenderedArticle(props: { content: string; }) { return {props.alt, hr: Seperator, h1: Heading, // TODO: fix this garbage h2: Heading, h3: Heading, h4: Heading, h5: Heading, h6: Heading, code: Code, }} />; } var collapsed = false; function toggle() { collapsed = !collapsed; document.documentElement.style.setProperty('--collapse-horizontal-gap', Number(collapsed).toString()); } export default function Post(props: { content: string; meta: ArticleMeta; }) { return
{props.meta.title} - Loek's Blog

{props.meta.title}

{props.meta.subtitle}

{props.meta.tags && }
; } var parseTag = { 'title': (val: string) => val, 'subtitle': (val: string) => val, 'author': (val: string) => val, 'cover': (val: string) => val, 'tags': (val: string) => val.split(',').map(i => i.trim()), 'date': (val: string) => new Date(val).toDateString(), }; function parseMeta(file: Array): ArticleMeta { var meta: ArticleMeta = {}; file.forEach(line => { if (!line.startsWith('[meta]: ')) return; var tags = line.match(/\[meta\]:\s+\<(.+?)\>\s+\((.+?)\)/); if (!tags || !tags[1] || !tags[2]) return; if (!parseTag.hasOwnProperty(tags[1])) return; meta[tags[1]] = parseTag[tags[1]](tags[2]); }); return meta; } function parseToCRecursive(headings: Array): Array { interface WIPchapter extends chapter { unparsedChildren?: Array; } var children: Array = []; var lowestLevel = headingLevel(headings[0]); var currentChildIndex = -1; for (var i in headings) { var localLevel = headingLevel(headings[i]); if (localLevel == lowestLevel) { var chapterName = headings[i].match(/^[#]+\s+(.+)/)[1]; children.push({ name: chapterName, sectionLink: '#' + sectionID(chapterName), unparsedChildren: [], }); currentChildIndex += 1; } else { children[currentChildIndex].unparsedChildren.push(headings[i]); } } children.map(child => { child.children = parseToCRecursive(child.unparsedChildren); delete child.unparsedChildren; return child; }); return children as Array; } function parseToC(file: Array): Array { var fileAsStr = file.join('\n'); fileAsStr = fileAsStr.replace(/```.*?```/gs, ''); // filter out code blocks from table of contents var fileAsArr = fileAsStr.split('\n'); var chapterStrings = fileAsArr.filter(line => line.startsWith('#')); return parseToCRecursive(chapterStrings); } function preprocessor(fileContent: string) { var fileAsArr = fileContent.split('\n'); var meta = parseMeta(fileAsArr); meta.chapters = parseToC(fileAsArr); var result = fileAsArr.join('\n').trim(); return { meta, result }; } export function getStaticProps(props: { params: { id: string; }; }) { var filename = join('posts/', props.params.id + '.md'); var filecontent = readFileSync(filename).toString().trim(); var parsed = preprocessor(filecontent); parsed.meta.id = props.params.id; return { props: { content: parsed.result, meta: parsed.meta, }, }; } export function getStaticPaths() { var files = readdirSync('posts').filter(f => f.endsWith('.md')); return { paths: files.map((f) => { return { params: { id: f.substr(0, f.length - 3), }, }; }), fallback: false, }; }